﻿using NavGuide.Guide;
using NavGuide.Guide.Dtos;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Xml;

namespace NavGuide.Web.Controllers
{
    public class GuideController : NavGuideControllerBase
    {
        protected string _FilePath = ConfigurationManager.AppSettings["FilePath"];

        private readonly INavigationAppService _navigationAppService;
        public GuideController(INavigationAppService navigationAppService)
        {
            _navigationAppService = navigationAppService;
        }
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Tree(string id = "")
        {
            GuideModel model = new GuideModel();

            var first = _navigationAppService.GetTree(id);
            var data = first.Items.FirstOrDefault();
            if (data != null)
            {
                model.id = data.Id;
                model.text = data.DisplayName;
                model.state = new State() { opened = true };
                if (data.Items != null && data.Items.Count > 0)
                {
                    var items = data.Items.OrderBy(s => s.DisplayName);
                    var childs = new List<GuideModel>();
                    foreach (var item in items)
                    {
                        var child = GetTreeNode(item);
                        childs.Add(child);
                    }

                    model.children = childs;
                }
            }

            return Json(model, JsonRequestBehavior.AllowGet);
        }

        private GuideModel GetTreeNode(NavigationDto dto)
        {
            GuideModel model = new GuideModel();
            model.id = dto.Id;
            model.text = dto.DisplayName;

            var childs = new List<GuideModel>();
            foreach (var item in dto.Items)
            {
                var child = GetTreeNode(item);
                childs.Add(child);
            }
            model.children = childs;
            return model;
        }

        public ActionResult Search(string search = "", string pid = "")
        {
            var list = _navigationAppService.GetList(search, pid);
            return View(list);
        }

        public ActionResult AddFolder(string pid)
        {
            NavigationDto dto = new NavigationDto();
            if (!string.IsNullOrWhiteSpace(pid))
            {
                var parent = _navigationAppService.Get(pid);
                if (parent != null)
                {
                    dto.ParentId = dto.ParentId;
                    dto.Name = parent.DisplayName;
                }
            }
            return View(dto);
        }

        public ActionResult Edit(string id)
        {
            var dto = _navigationAppService.Get(id);
            if (!string.IsNullOrWhiteSpace(dto.ParentId))
            {
                var parent = _navigationAppService.Get(dto.ParentId);
                dto.Name = parent.DisplayName;
            }
            else
            {
                dto.Name = "";
            }

            return View("AddFolder", dto);
        }

        [HttpPost]
        public ActionResult Add(NavigationDto dto)
        {
            if (string.IsNullOrWhiteSpace(dto.Id))
            {

                _navigationAppService.Add(dto);
            }
            else
            {
                _navigationAppService.Edit(dto);
            }
            return Json(new { code = 1, msg = "操作成功" }, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Import()
        {
            return View("Import");
        }


        /// <summary>
        /// 从上传的Excel数据中批量导入用户信息
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult ImportFromExcel()
        {
            try
            {
                var files = Request.Files;
                if (files.Count > 0)
                {
                    var httpPostedFileBase = Request.Files[0];
                    if (httpPostedFileBase != null)
                    {
                        if (httpPostedFileBase.FileName.EndsWith("html"))
                        {
                            var file = UploadFile(Request.Files[0], _FilePath);
                            using (FileStream fs = new FileStream(file.SavePath, FileMode.OpenOrCreate, FileAccess.Read))
                            {
                                using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
                                {
                                    string folderStr = "";
                                    string content = sr.ReadToEnd();
                                    content = Filter(content);
                                    var root = GetGuide(content);
                                    if (!_navigationAppService.HasRoot())
                                    {
                                        Insert(null, root.Text, "", false);
                                    }


                                    foreach (var folder in root.Folders)
                                    {
                                        ImportNode(folder, "1");
                                    }
                                    foreach (var link in root.Links)
                                    {
                                        Insert("1", link.Text, link.Link, true);
                                    }
                                    //var nav  = _navigationAppService.Get()
                                }
                            }

                            return new JsonNetSuccessResult("导入成功！");
                        }
                        else
                        {
                            return new JsonNetErrorResult("上传文件不合法！");
                        }
                    }
                }


            }
            catch (Exception ex)
            {
                Logger.Debug("ImportFromExcel:", ex);
            }
            return Json("上传文件时出现错误！");
        }

        public void ImportNode(FolderModel model, string parentId)
        {
            var id = Insert(parentId, model.Text, "", false);
            foreach (var folder in model.Folders)
            {
                ImportNode(folder, id);
            }

            foreach (var link in model.Links)
            {
                Insert(id, link.Text, link.Link, true);
            }
        }

        public string Insert(string parentId, string name, string url, bool isLeaf)
        {
            NavigationDto dto = new NavigationDto()
            {
                ParentId = parentId,
                DisplayName = name,
                Url = url,
                IsLeaf = isLeaf
            };

            return _navigationAppService.Import(dto);
        }


        public string Filter(string data)
        {
            data = data.Split(new string[] { "<H1>Bookmarks</H1>" }, StringSplitOptions.RemoveEmptyEntries)[1];
            data = data.Replace("<p>", "").Replace("<DT><H3", "<H3").Replace("<DT><A HREF", "<A HREF");


            return data;
        }

        public FolderModel GetGuide(string data)
        {

            data = data.Trim('\r').Trim('\n');
            var rows = data.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            rows[0] = "";
            rows[rows.Length - 1] = "";

            FolderModel root = new FolderModel();
            root.Text = "收藏夹";
            root.Folders = new List<FolderModel>();
            FolderModel node1 = new FolderModel();
            FolderModel node2 = new FolderModel();
            FolderModel node3 = new FolderModel();

            root.Folders = new List<FolderModel>();
            foreach (var row in rows)
            {
                var tag = GetNodeTag(row);
                switch (tag)
                {
                    case NodeTag.H3Start:
                        {
                            node1 = new FolderModel();
                            node1.Folders = new List<FolderModel>();
                            node1.Text = GetHeadNode(row, "").Text;
                            break;
                        }
                    case NodeTag.tH3Start:
                        {
                            node2 = new FolderModel();
                            node2.Folders = new List<FolderModel>();
                            node2.Text = GetHeadNode(row, "t").Text;
                            break;
                        }
                    case NodeTag.ttH3Start:
                        {
                            node3 = new FolderModel();
                            node3.Folders = new List<FolderModel>();
                            node3.Text = GetHeadNode(row, "tt").Text;
                            break;
                        }
                    case NodeTag.AStart:
                        {
                            root.Links.Add(GetLinkNode(row, ""));
                            break;
                        }
                    case NodeTag.tAStart:
                        {
                            node1.Links.Add(GetLinkNode(row, "t"));
                            break;
                        }
                    case NodeTag.ttAStart:
                        {
                            node2.Links.Add(GetLinkNode(row, "tt"));
                            break;
                        }
                    case NodeTag.tttAStart:
                        {
                            node3.Links.Add(GetLinkNode(row, "ttt"));
                            break;
                        }
                    case NodeTag.DlStart:
                        {

                            break;
                        }
                    case NodeTag.DlEnd:
                        {
                            root.Folders.Add(node1);
                            break;
                        }
                    case NodeTag.tDlStart:
                        {

                            break;
                        }
                    case NodeTag.tDlEnd:
                        {
                            node1.Folders.Add(node2);
                            break;
                        }
                    case NodeTag.ttDlStart:
                        {

                            break;
                        }
                    case NodeTag.ttDlEnd:
                        {
                            node2.Folders.Add(node3);
                            break;
                        }
                    default: break;
                }
            }
            return root;
        }

        public NodeTag GetNodeTag(string row)
        {
            //string regex = "<H3 FOLDED ADD_DATE=\"(\\d)*\" FAV_POS=\"0\">.*|</H3>";

            if (new Regex("^<H3").IsMatch(row))
            {
                return NodeTag.H3Start;
            }
            if (new Regex("^[\t]<H3").IsMatch(row))
            {
                return NodeTag.tH3Start;
            }
            if (new Regex("^[\t][\t]<H3").IsMatch(row))
            {
                return NodeTag.ttH3Start;
            }
            if (new Regex("^<A").IsMatch(row))
            {
                return NodeTag.AStart;
            }
            if (new Regex("^[\t]<A").IsMatch(row))
            {
                return NodeTag.tAStart;
            }
            if (new Regex("^[\t][\t]<A").IsMatch(row))
            {
                return NodeTag.ttAStart;
            }
            if (new Regex("^[\t][\t][\t]<A").IsMatch(row))
            {
                return NodeTag.tttAStart;
            }

            if (new Regex("^<DL").IsMatch(row))
            {
                return NodeTag.DlStart;
            }
            if (new Regex("^[\t]<DL").IsMatch(row))
            {
                return NodeTag.tDlStart;
            }
            if (new Regex("^[\t][\t]<DL").IsMatch(row))
            {
                return NodeTag.ttDlStart;
            }

            if (new Regex("^</DL").IsMatch(row))
            {
                return NodeTag.DlEnd;
            }
            if (new Regex("^[\t]</DL").IsMatch(row))
            {
                return NodeTag.tDlEnd;
            }
            if (new Regex("^[\t][\t]</DL").IsMatch(row))
            {
                return NodeTag.ttDlEnd;
            }

            return NodeTag.Null;
        }

        public LinksModel GetLinkNode(string row, string t)
        {
            string text = "";
            string link = "";
            string regStr = @"(?is)<a[^>]*?href=(['""]?)(?<url>[^'""\s>]+)\1[^>]*>(?<text>(?:(?!</?a\b).)*)</a>";
            if (t == "t") regStr = @"(?is)[\t]<a[^>]*?href=(['""]?)(?<url>[^'""\s>]+)\1[^>]*>(?<text>(?:(?!</?a\b).)*)</a>";
            if (t == "tt") regStr = @"(?is)[\t][\t]<a[^>]*?href=(['""]?)(?<url>[^'""\s>]+)\1[^>]*>(?<text>(?:(?!</?a\b).)*)</a>";
            if (t == "ttt") regStr = @"(?is)[\t][\t][\t]<a[^>]*?href=(['""]?)(?<url>[^'""\s>]+)\1[^>]*>(?<text>(?:(?!</?a\b).)*)</a>";
            Regex reg = new Regex(regStr);
            MatchCollection mc = reg.Matches(row);
            foreach (Match m in mc)
            {
                link = m.Groups["url"].Value;//得到href值                 
                text = m.Groups["text"].Value;//得到<a></a>中间的内容           
            }

            return new LinksModel() { Text = text, Link = link };
        }

        public FolderModel GetHeadNode(string row, string t)
        {
            string text = "";
            string regStr = @"(?is)<h3[^>]*>(?<text>(?:(?!</?a\b).)*)</h3>";
            if (t == "t") regStr = @"(?is)[\t]<h3[^>]*>(?<text>(?:(?!</?a\b).)*)</h3>";
            if (t == "tt") regStr = @"(?is)[\t][\t]<h3[^>]*>(?<text>(?:(?!</?a\b).)*)</h3>";
            Regex reg = new Regex(regStr);
            MatchCollection mc = reg.Matches(row);
            foreach (Match m in mc)
            {
                text = m.Groups["text"].Value;//得到<h3></h3>中间的内容           
            }

            return new FolderModel() { Text = text };
        }
    }

    public enum NodeTag
    {
        AStart,
        H3Start,
        DlStart,
        DlEnd,
        tAStart,
        tH3Start,
        tDlStart,
        tDlEnd,
        ttAStart,
        ttH3Start,
        ttDlStart,
        ttDlEnd,
        tttAStart,
        Null
    }

    public class GuideModel
    {
        public string id { get; set; }
        public string text { get; set; }
        public State state { get; set; }

        public List<GuideModel> children { get; set; }
    }
    public class State
    {
        public bool opened { get; set; }
        public bool disabled { get; set; }
        public bool selected { get; set; }
    }

    public class FolderModel
    {
        public FolderModel()
        {
            Links = new List<LinksModel>();
        }
        public string Text { get; set; }
        public List<FolderModel> Folders { get; set; }
        public List<LinksModel> Links { get; set; }
    }

    public class LinksModel
    {
        public string Text { get; set; }
        public string Link { get; set; }
    }
}